package com.inspur.edp.udt.designtime.manager.services;


import com.inspur.edp.bef.bizentity.GspBizEntityElement;
import com.inspur.edp.bef.bizentity.GspBusinessEntity;
import com.inspur.edp.cef.designtime.api.IGspCommonField;
import com.inspur.edp.cef.designtime.api.element.GspAssociation;
import com.inspur.edp.cef.designtime.api.element.GspElementObjectType;
import com.inspur.edp.das.commonmodel.IGspCommonElement;
import com.inspur.edp.das.commonmodel.entity.element.GspCommonAssociation;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.lcm.metadata.api.service.RefCommonService;
import com.inspur.edp.udt.designtime.api.entity.ComplexDataTypeDef;
import com.inspur.edp.udt.designtime.api.entity.SimpleDataTypeDef;
import com.inspur.edp.udt.designtime.api.entity.element.UdtElement;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;
import io.iec.edp.caf.tenancy.core.utils.DataValidator;
import lombok.var;

import java.util.ArrayList;

public class UpdateAssoRefElementUtil {

  private String errorCode = "UpdateAssoRefElementUtil";

  public static UpdateAssoRefElementUtil getInstance() {
    return new UpdateAssoRefElementUtil();
  }

  private java.util.HashMap<String, GspBusinessEntity> beDic = new java.util.HashMap<String, GspBusinessEntity>();
  private java.util.ArrayList<IGspCommonField> fieldList = new java.util.ArrayList<IGspCommonField>();
  private RefCommonService lcmDtService;

  private RefCommonService getLcmDtService() {
    if (lcmDtService == null) {
      lcmDtService = SpringBeanUtils.getBean(RefCommonService.class);
    }
    return lcmDtService;
  }

  public final void handleUdtAssos(GspMetadata udtMeta) {

    var udt = udtMeta.getContent();
    if (udt instanceof SimpleDataTypeDef
        && ((SimpleDataTypeDef) udt).getObjectType() == GspElementObjectType.Association) {

      var assos = ((SimpleDataTypeDef) udt).getChildAssociations();
      if (assos != null && assos.size() > 0) {

        for (var asso : assos) {
          handleUdtAsso((SimpleDataTypeDef) udt, asso);
        }
      }
    }
  }

  private void handleUdtAsso(SimpleDataTypeDef udt, GspAssociation asso) {
    getBeElements(asso.getRefModelID());

    var refEles = asso.getRefElementCollection();

    for (var refEle : refEles) {
      IGspCommonField ele = fieldList.stream()
          .filter((item) -> item.getID().equals(refEle.getRefElementId())).findFirst().orElse(null);
      DataValidator.checkForNullReference(ele,
          "UDT{" + udt.getName() + "}上的关联带出字段{" + refEle.getName() + "}在对应的BE上找不到，RefElementID：{"
              + refEle.getRefElementId() + "}");
      DataValidator.checkForNullReference((UdtElement) refEle, "(UdtElement)refEle");
      HandleRefElement((UdtElement) refEle, ele, udt);
    }
  }

  private void getBeElements(String beId) {
    if (beDic.containsKey(beId)) {
      return;
    }

    GspBusinessEntity be = (GspBusinessEntity) (
        (getLcmDtService().getRefMetadata(beId).getContent() instanceof GspBusinessEntity)
            ? getLcmDtService().getRefMetadata(beId).getContent() : null);
    beDic.put(beId, be);

    ArrayList<IGspCommonElement> eles = new ArrayList<>();
    if(be != null){
      be.getAllElementList(false);
    }
    fieldList.addAll(eles);

    for (IGspCommonElement ele : eles) {
      if (ele.getChildAssociations() != null && ele.getChildAssociations().size() > 0) {

        for (GspAssociation asso : ele.getChildAssociations()) {
          //getBeElements(asso.RefModelID);

          for (var item : asso.getRefElementCollection()) {
            fieldList.add(item);
          }
        }

      }
    }
  }

  private void HandleRefElement(UdtElement refEle, IGspCommonField ele, SimpleDataTypeDef sUdt) {
    // 数据类型
    refEle.setMDataType(ele.getMDataType());
    refEle.setIsUdt(ele.getIsUdt());
    refEle.setUdtID(ele.getUdtID());
    refEle.setUdtName(ele.getUdtName());
    refEle.setUdtPkgName(ele.getUdtPkgName());

    // 对象类型
    refEle.setObjectType(ele.getObjectType());
    refEle.getContainEnumValues().clear();
    refEle.getChildAssociations().clear();
    switch (ele.getObjectType()) {
      case Association:
        //if (ele.ChildAssociations.Count > 0)
        //{
        //	foreach (var ass in ele.ChildAssociations)
        //	{
        //		refEle.ChildAssociations.Add(ConvertToUdtAssociation(ass, ele as IGspCommonElement));
        //	}
        //}
        break;
      case Enum:
        if (ele.getContainEnumValues().size() > 0) {

          for (var enumValue : ele.getContainEnumValues()) {
            refEle.getContainEnumValues().add(enumValue);
          }
        }
        break;
      case None:
        break;
    }
  }


  ///#region 关联
  private GspAssociation ConvertToUdtAssociation(GspAssociation ass, IGspCommonElement ele) {
    GspCommonAssociation udtAsso = new GspCommonAssociation();
    udtAsso.setId(ass.getId());
    udtAsso.setRefModel(ele.getBelongObject().getBelongModel());
    udtAsso.setRefObjectCode(ass.getRefObjectCode());
    udtAsso.setRefModelID(ass.getRefModelID());
    udtAsso.setRefModelName(ass.getRefModelName());
    udtAsso.setRefModelPkgName(ass.getRefModelPkgName());
    udtAsso.setRefObjectCode(ass.getRefObjectCode());
    udtAsso.setRefObjectID(ass.getRefObjectID());
    udtAsso.setRefObjectName(ass.getRefObjectName());

    if (ass.getRefElementCollection().size() > 0) {
      for (IGspCommonField refEle : ass.getRefElementCollection()) {
        udtAsso.getRefElementCollection().add(ConvertToUdtRefElement(
            (GspBizEntityElement) ((refEle instanceof GspBizEntityElement) ? refEle : null)));
      }
    }

    return udtAsso;
  }

  private UdtElement ConvertToUdtRefElement(GspBizEntityElement bizEle) {
    UdtElement udtEle = new UdtElement(new ComplexDataTypeDef().getPropertys());
    udtEle.setID(bizEle.getID());
    udtEle.setLabelID(bizEle.getLabelID());
    udtEle.setCode(bizEle.getCode());
    udtEle.setName(bizEle.getName());
    udtEle.setMDataType(bizEle.getMDataType());
    udtEle.setLength(bizEle.getLength());
    udtEle.setPrecision(bizEle.getPrecision());
    udtEle.setRefElementId(bizEle.getRefElementId());
    udtEle.setIsRefElement(true);
    udtEle.setIsFromAssoUdt(true);

    // udt相关
    udtEle.setIsUdt(bizEle.getIsUdt());
    udtEle.setUdtID(bizEle.getUdtID());
    udtEle.setUdtName(bizEle.getUdtName());
    udtEle.setUdtPkgName(bizEle.getUdtPkgName());
    return udtEle;
  }

  ///#endregion
}